#include "stdafx.h"

#include "InputManager.h"
#include "camera/Camera.h"
#include "terrain/Terrain.h"

#define IS_KEY_PRESSED(Key, buf, action)    \
if ( glfwGetKey(Key) )                      \
{                                           \
    keyPrevList[Key] = 1;                   \
}                                           \
else if(keyPrevList[Key])                   \
{                                           \
    action;                                 \
    keyPrevList[Key] = 0;                   \
}                                           \

#define IS_KEY_DOWN(Key, buf, action)       \
if ( glfwGetKey(Key) )                      \
    action;                                 \

InputManager::InputManager() : keyboardState(KEYS_LEN), mouseButtonState(MOUSE_LEN)
{

}
InputManager::~InputManager(){}

void InputManager::update() 
{
	for (unsigned int i = 0; i < keyboardState.size(); ++i) {
		keyboardState[i] = glfwGetKey(Game::window, key_ind[i]);
	}

	for (unsigned int i = 0; i < mouseButtonState.size(); ++i) {
		mouseButtonState[i] = glfwGetMouseButton(Game::window, mouse_ind[i]);
	}

	glfwGetCursorPos(Game::window, &mousePosState[0], &mousePosState[1]);
}

bool InputManager::isKeyClicked(Key key)
{
    assert(key < KEYS_LEN);

    if ( keyboardState[key] )  
    {
        keyPrevList[key] = 1;    
    }
    else if(keyPrevList[key])
    {   
        keyPrevList[key] = 0;    
        return true;
    } 
    return false;
}

bool InputManager::isKeyClickedLocal(int key) {
	return glfwGetKey(Game::window, key) == GLFW_PRESS;
}

bool InputManager::isKeyPressed(Key key)
{
    return keyboardState[key] == 1;
}

bool InputManager::isMouseClicked(MouseButton mouseButton)
{
	assert(mouseButton <= 8);

	if (mouseButtonState[mouseButton]) {
		mouseButPrevList[mouseButton] = 1;
	}
	else if (mouseButPrevList[mouseButton]) {
		mouseButPrevList[mouseButton] = 0;
		return true;
	}
	return false;
}

bool InputManager::isMousePressed(MouseButton mouseButton)
{
    return mouseButtonState[mouseButton] == GLFW_PRESS;
}

glm::dvec2 InputManager::getMousePos() 
{
    return glm::dvec2(mousePosState[0], mousePosState[1]);
}

void InputManager::encode(std::vector<unsigned char>& targetBuf, unsigned int offset) 
{
	//std::string keyPrevAsString = keyPrevList.to_string();
	//std::string mousePrevAsString = mouseButPrevList.to_string();

	::resizeIf(targetBuf, offset + 
		(keyboardState.size() + mouseButtonState.size())*sizeof(int) + 
		sizeof(glm::dvec2));

	memcpy(&targetBuf[offset], &keyboardState[0], keyboardState.size()*sizeof(int));
	offset += keyboardState.size()*sizeof(int);
	memcpy(&targetBuf[offset], &mouseButtonState[0], mouseButtonState.size()*sizeof(int));
	offset += mouseButtonState.size()*sizeof(int);
	memcpy(&targetBuf[offset], &mousePosState[0], 2*sizeof(double));

    /* serialize all player input such that other clients may replicate behavior */
    /* i.e: all input state seen now: every key pressed / mouse held etc */
}

void InputManager::decode(std::vector<unsigned char>& serializedBuf) {
	unsigned int offset = 0;
	memcpy(&keyboardState[0], &serializedBuf[offset], keyboardState.size()*sizeof(int));
	offset += keyboardState.size()*sizeof(int);
	memcpy(&mouseButtonState[0], &serializedBuf[offset], mouseButtonState.size()*sizeof(int));
	offset += mouseButtonState.size()*sizeof(int);
	memcpy(&mousePosState[0], &serializedBuf[offset], 2*sizeof(double));

	///*LOG(*/std::printf(": %g %g\n", mousePosState[0], mousePosState[1]);
}